#include <stdio.h>
#include <string.h> 
#include <stdlib.h>
#include "ina22x_driver.h"
#include "../Debug/debug_driver.h"

typedef struct
{
    char name[8];
    char version[8];
    WHT_INA226_Info_t INA226_Info[Alert_COUNT];
}WHT_Flash_Info_t;


static WHT_Flash_Info_t WHT_Flash_Info;

static WHT_INA226_Value_t WHT_INA226_Value[Alert_COUNT];

static void APP_VI_Task(void* parameter)
{
    strcpy(WHT_Flash_Info.name, "WHT");
    strcpy(WHT_Flash_Info.version, "V1.0.0");

    for (size_t i = 0; i < sizeof(WHT_Flash_Info.INA226_Info) / sizeof(WHT_Flash_Info.INA226_Info[0]); i++)
    {
        WHT_Flash_Info.INA226_Info[i].Config.Addr = (WHT_INA22x_Addr_enum)(INA22x_7Bit_Addr1 + i);
        WHT_Flash_Info.INA226_Info[i].Config.Mode = INA226_V_I_Continuous_Mode;
        WHT_Flash_Info.INA226_Info[i].Config.Convert_Time = CNV_Time_19ms;

        WHT_Flash_Info.INA226_Info[i].Config.Alert_SHNTOL = DISABLE;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_SHNTUL = DISABLE;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_BUSOL = DISABLE;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_BUSUL = DISABLE;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_POL = DISABLE;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_CNVR = ENABLE;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_APOL = Low;
        WHT_Flash_Info.INA226_Info[i].Config.Alert_ALATCH = ENABLE;

        WHT_Flash_Info.INA226_Info[i].Config.Calibration_Shunt_Gain_Val = 0;
        WHT_Flash_Info.INA226_Info[i].Config.Calibration_VBus_Gain_Val = 1.0f;
        WHT_Flash_Info.INA226_Info[i].Config.Sampling_Res_Milliohm = INA22x_Sampling_Res_10Milliohm;
    }

    for (size_t i = 0; i < sizeof(WHT_Flash_Info.INA226_Info) / sizeof(WHT_Flash_Info.INA226_Info[0]); i++)
    {
        WHT_Flash_Info.INA226_Info[i].Result = &WHT_INA226_Value[i];
        WHT_INA226_Driver.WHT_Init(&WHT_Flash_Info.INA226_Info[i]);
    }


	for (; ;)
	{
        for (uint8_t i = 0; i < Alert_COUNT; i++)
        {
            if (WHT_INA22x_Alert_Status.WHT_Get_Alert_Status(i) == Alert_Open)
            {
                WHT_INA226_Driver.WHT_Get_Voltage(&WHT_Flash_Info.INA226_Info[i]);
                WHT_INA226_Driver.WHT_Get_Current(&WHT_Flash_Info.INA226_Info[i]);
                WHT_INA226_Driver.WHT_Get_Alert_Flag(&WHT_Flash_Info.INA226_Info[i]);
                vTaskDelay(1 / portTICK_RATE_MS);
            }
        }
		vTaskDelay(3 / portTICK_RATE_MS);
	}
}

static void APP_VI_Debug_Task(void* parameter)
{
    uint8_t Debug_Flag = DISABLE;
    uint8_t Calibration_Flag = DISABLE;
    uint8_t Calibration_CHx;
    uint8_t Calibration_Voltage_Flag;
    uint8_t Calibration_Current_Flag;
    float Calibration_Voltage;
    float Calibration_Current;
    char TRx_Buffer[64];

	for (; ;)
	{
        if (Debug_Flag == ENABLE)
        {
            for (size_t i = 0; i < sizeof(WHT_Flash_Info.INA226_Info) / sizeof(WHT_Flash_Info.INA226_Info[0]); i++)
            {
                printf("CH%d:%.0fmA %.0fmV\r\n", i, WHT_Flash_Info.INA226_Info[i].Result->Current_mA, WHT_Flash_Info.INA226_Info[i].Result->Voltage_mV);
            }
            printf("\r\n");
        }

        if (WHT_Debug_Driver.WHT_Scanf((uint8_t*)TRx_Buffer, sizeof(TRx_Buffer), 400) != 0)
        {
            //Start_Calibration_Gain:DC_Voltage=5V,DC_Current=5A,CH=0
            if (strncmp(TRx_Buffer, "Start Debug",11) == 0)
            {
                Debug_Flag = ENABLE;
                printf("Voltage Current Log Start\r\n");
            }
            else if (strncmp(TRx_Buffer, "Stop Debug",10) == 0)
            {
                Debug_Flag = DISABLE;
                printf("Voltage Current Log Stop\r\n");
            }
            else if (strncmp(TRx_Buffer, "Start_Calibration_Gain:",23) == 0)
            {
                uint8_t data_flag = ENABLE;
                char* pos;
                pos = strstr(TRx_Buffer,"DC_Voltage=");
                if (pos)
                {
                    Calibration_Voltage = atof(pos+11) * 1000;
                    printf("Calibration_Voltage=%.0fmV\r\n", Calibration_Voltage);
                }
                else
                {
                    data_flag = DISABLE;
                    printf("Calibration_Voltage ERROR\r\n");
                }
                pos = strstr(TRx_Buffer,"DC_Current=");
                if (pos)
                {
                    Calibration_Current = atof(pos+11) * 1000;
                    printf("Calibration_Current=%.0fmA\r\n",Calibration_Current);
                }
                else
                {
                    data_flag = DISABLE;
                    printf("Calibration_Current ERROR\r\n");
                }
                pos = strstr(TRx_Buffer,"CH=");
                if (pos)
                {
                    Calibration_CHx = atoi(pos+3);
                    printf("Calibration_CHx=%d\r\n", Calibration_CHx);
                    if (Calibration_CHx >= Alert_COUNT)
                    {
                        data_flag = DISABLE;
                        printf("Calibration_CHx ERROR\r\n");
                    }
                }
                else
                {
                    data_flag = DISABLE;
                    printf("Calibration_CHx ERROR\r\n");
                }
                if (data_flag == ENABLE)
                {
                    WHT_Flash_Info.INA226_Info[Calibration_CHx].Config.Calibration_VBus_Gain_Val = 1.0f;
                    Calibration_Voltage_Flag = DISABLE;
                    Calibration_Current_Flag = ENABLE;
                    Calibration_Flag = ENABLE;
                }
            }
            else
            {
                printf("Cmd:Start Debug OR Stop Debug\r\n");
                printf("Cmd:DC_Voltage=xV,DC_Current=xA,CH=x\r\n");
            }
        }
        if (Calibration_Flag == ENABLE)
        {
            if (Calibration_Voltage_Flag == ENABLE)
            {
                if (abs(WHT_Flash_Info.INA226_Info[Calibration_CHx].Result->Voltage_mV - Calibration_Voltage) > 2.2f)
                {
                    WHT_Flash_Info.INA226_Info[Calibration_CHx].Config.Calibration_VBus_Gain_Val = Calibration_Voltage / WHT_Flash_Info.INA226_Info[Calibration_CHx].Result->Voltage_mV;
                }
                else
                {
                    Calibration_Voltage_Flag = DISABLE;
                    printf("CH%d:Voltage Calibration OK\r\n", Calibration_CHx);
                    /* 这里可以保存 WHT_Flash_Info内的数据到EEPROM里 */
                }
            }
            if (Calibration_Current_Flag == ENABLE)
            {
                if ((WHT_Flash_Info.INA226_Info[Calibration_CHx].Result->Current_mA - Calibration_Current) < -3)
                {
                    WHT_Flash_Info.INA226_Info[Calibration_CHx].Config.Calibration_Shunt_Gain_Val++;
                    WHT_INA226_Driver.WHT_Set_Calibration_Shunt_Gain(&WHT_Flash_Info.INA226_Info[Calibration_CHx]);
                }
                else if ((WHT_Flash_Info.INA226_Info[Calibration_CHx].Result->Current_mA - Calibration_Current) > 3)
                {
                    WHT_Flash_Info.INA226_Info[Calibration_CHx].Config.Calibration_Shunt_Gain_Val--;
                    WHT_INA226_Driver.WHT_Set_Calibration_Shunt_Gain(&WHT_Flash_Info.INA226_Info[Calibration_CHx]);
                }
                else
                {
                    Calibration_Current_Flag = DISABLE;
                    printf("CH%d:Current Calibration OK\r\n",Calibration_CHx);
                    /* 这里可以保存 WHT_Flash_Info内的数据到EEPROM里 */
                }
                printf("CAL=%u\r\n",WHT_Flash_Info.INA226_Info[Calibration_CHx].Config.Calibration_Shunt_Gain_Val);
            }
            if ((Calibration_Voltage_Flag == DISABLE) && (Calibration_Current_Flag == DISABLE))
            {
                Calibration_Flag = DISABLE;
            }
        }
	}
}




void APP_VI_Init(uint8_t Priority)
{
    xTaskCreate(APP_VI_Task, "APP_VI_Task", 128, NULL, Priority, NULL);
    xTaskCreate(APP_VI_Debug_Task, "APP_VI_Debug_Task", 200, NULL, Priority-2, NULL);
}
